
#include "sysdef.h"





MODULE_AUTHOR( DRIVER_AUTHOR );   
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");


//============================================================
//vender ID and product ID can into here for others
//============================================================
static struct usb_device_id Id_Table[] = 
{
  {USB_DEVICE( 0x0416, 0x0035 )},	
  {USB_DEVICE( 0x18E8, 0x6201 )},	
  {USB_DEVICE( 0x18E8, 0x6206 )},	
  {USB_DEVICE( 0x18E8, 0x6217 )},	
  {USB_DEVICE( 0x18E8, 0x6230 )},	
  {USB_DEVICE( 0x18E8, 0x6233 )},	
  {USB_DEVICE( 0x1131, 0x2035 )},
  {  }
}
;
MODULE_DEVICE_TABLE(usb,Id_Table);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
	static struct usb_driver wb35_driver = {
			name:	    "w35und",
			probe:		wb35_probe,
			disconnect:	wb35_disconnect,
			id_table:   Id_Table,
	};
#else
	static struct usb_driver wb35_driver = {
			.name =		"w35und",
			.probe =	wb35_probe,
			.disconnect = wb35_disconnect,
			.id_table = Id_Table,
	};
#endif

int __init wb35_init( void )
{
    #ifdef _PE_USB_INI_DUMP_
	WBDEBUG(("sizeof ADAPTER = %d\n", sizeof(ADAPTER) ));
	WBDEBUG(("[w35und]driver init\n"));
    #endif
	return usb_register( &wb35_driver );
}

void __exit wb35_exit( void )
{
    #ifdef _PE_USB_INI_DUMP_
	WBDEBUG(("[w35und]driver exit\n"));
    #endif
    usb_deregister( &wb35_driver );
}

module_init( wb35_init );
module_exit( wb35_exit );

//Usb kernel subsystem will call this function when a new device is plugged into.
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
void *wb35_probe( struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id_table )
#else
int wb35_probe( struct usb_interface *intf,const struct usb_device_id *id_table )
#endif
{
	PADAPTER	Adapter;
	PWBLINUX	pWbLinux;
	PWBUSB		pWbUsb;
	struct net_device *netdev = NULL;

        struct usb_host_interface *interface;
   
   //struct usb_interface_descriptor *interface;
    struct usb_endpoint_descriptor *endpoint;
	int	i, ret = -1;
	ULONG	ltmp;


#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
	struct usb_device *udev = interface_to_usbdev(intf);
	int res = -ENOMEM;
	usb_get_dev(udev);
#endif

    #ifdef _PE_USB_INI_DUMP_
	WBDEBUG(("[w35und]wb35_probe ->\n"));
    #endif

	do
	{
		#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
		if( usb_set_configuration( udev, udev->config[0].bConfigurationValue ) ) 
		{
			#ifdef _PE_USB_INI_DUMP_
			WBDEBUG(("[w35und]usb_set_configuration() failed\n"));
			#endif
			break;
		}
		#endif

		// 20060630.1 Add for check HW basically
		for( i=0; i<(sizeof(Id_Table)/sizeof(struct usb_device_id)); i++ )
		{
			if( (udev->descriptor.idVendor == Id_Table[i].idVendor) &&
				(udev->descriptor.idProduct == Id_Table[i].idProduct) )
			{
				#ifdef _PE_USB_INI_DUMP_
				WBDEBUG(("[w35und]This is the one we are interested about\n"));
				#endif
				break;
			}
		}
		if( i == (sizeof(Id_Table)/sizeof(struct usb_device_id)) )
		{
			#ifdef _PE_USB_INI_DUMP_
			WBDEBUG(("[w35und] This is not the one we are interested about\n"));
			#endif
		   //Devuelve NULL en un int?? , donde definio NULL si es para otro OS?
			return res;
		}

		// 20060630.2 Check the device if it already be opened
		ret = usb_control_msg( udev,
					   usb_rcvctrlpipe( udev, 0 ),
					   0x01,
					   USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
					   0x0, 0x400,
					   &ltmp,
					   4, HZ*100 );
		if( ret < 0 )
			break;
		ltmp = cpu_to_le32(ltmp);

		if( ltmp ) // Is already initialized?
			break;


		#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
		netdev = init_etherdev( NULL, sizeof(ADAPTER) );
		#else
		netdev = alloc_etherdev( sizeof(ADAPTER) );
		#endif

		if( !netdev )
		{
			#ifdef _PE_USB_INI_DUMP_
			WBDEBUG(("[w35und]init_etherdev out of memory\n"));
			#endif

			#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
			module_put(THIS_MODULE);
			#endif

			break;
		}

		// Clear out the adapter block, which sets all default values to FALSE, or NULL.
		#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
		Adapter = netdev->priv;
		#else
		Adapter = netdev_priv( netdev );
		#endif

		OS_MEMORY_CLEAR( Adapter, sizeof(ADAPTER) );
		pWbLinux = &Adapter->WbLinux;
		pWbLinux->netdev = netdev; // Initial netdev variable of WbLinux
		pWbUsb = &Adapter->sHwData.WbUsb;
		pWbUsb->udev = udev;

		//set the interface name for this device.
		//dev_alloc_name(	netdev, "wlan%d");

		//to fill the owner field of netdev for kernel usage count 
	       #if  LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)  
	       SET_MODULE_OWNER( netdev );
	       #endif
		// Determine that the USB type is working at 1.1 or 2.0
		#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
		interface = udev->config[0].interface[ifnum].altsetting;
		endpoint = interface[ifnum].endpoint;
		#else
	        //Cambiado
	        interface = intf->cur_altsetting;
	        endpoint = &interface->endpoint[0].desc;

	   	   //&(intf->altsetting->endpoint);
		#endif

		if( endpoint[2].wMaxPacketSize == 512 )
		{
			#ifdef _PE_USB_INI_DUMP_
			WBDEBUG(("[w35und] Working on USB 2.0\n"));
			#endif
			pWbUsb->IsUsb20 = 1;
		}
		#ifdef _PE_STATE_DUMP_	
		WBDEBUG(("WbWLanInitialize(1)\n"));
		#endif
		if( !WbWLanInitialize( Adapter ) )
		{
			#ifdef _PE_USB_INI_DUMP_
			WBDEBUG(("[w35und]WbWLanInitialize fail\n"));
			#endif
			break;
		}
		//For test,Added by WangJS 2006.9.1
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("WbWLanInitialize(2)\n"));
		#endif

		//Set MAC Address - by Someone - since 2.6.24-rc2
		{
		phw_data_t pHwData = &Adapter->sHwData;
		hal_get_permanent_address( pHwData, netdev->dev_addr );
		}

		//////////////////////////////////////////////////
		//Added by WangJS 2006.7.28
		FourWayInit(Adapter);
		//////////////////////////////////////////////////

		//Moved later, to make possible the changing of MAC
		//Needs some more work
		dev_alloc_name(	netdev, "wlan%d");

		#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
		SET_NETDEV_DEV( netdev, &intf->dev );
		if( register_netdev( netdev ) !=0 )
		{
			#ifdef _PE_USB_INI_DUMP_
			WBDEBUG(("couldn't register the device of net !\n"));
			#endif
			break;
		}
		usb_set_intfdata( intf, Adapter );
		#endif

		#ifdef _PE_USB_INI_DUMP_
		WBDEBUG(("[w35und] _probe OK\n"));
		#endif

		#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
		return Adapter;
		#else
		return 0;
		#endif

	}while(FALSE);

	#if LINUX_VERSION_CODE <KERNEL_VERSION(2,5,0)
	if( Adapter )
		kfree( Adapter );
	if( netdev )
		kfree( netdev );
	return NULL;
	#else
	if( netdev )
		free_netdev( netdev );
	return -ENOMEM;
	#endif
}

BOOL
WbUsb_initial( IN phw_data_t pHwData )
{
	return 1;
}


VOID
WbUsb_destroy( IN phw_data_t pHwData )
{
}

int wb35_open( struct net_device *netdev )
{
	PADAPTER Adapter = (PADAPTER)netdev->priv;
	phw_data_t pHwData = &Adapter->sHwData;
        #ifdef _PE_USB_INI_DUMP_
        u8 mac_addr[8];   
	int ep_cnt=0;
        #endif

//	This needs to be in wb35_probe, moved - Scythe
//	hal_get_permanent_address( pHwData, netdev->dev_addr );
        netif_start_queue(netdev);

	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
	MOD_INC_USE_COUNT;
	#endif

	#ifdef _PE_USB_INI_DUMP_

	WBDEBUG(("[w35und] MAC ADDR: "));
	for( ep_cnt = 0; ep_cnt < 6; ep_cnt++ )
	{
		WBDEBUG(("%x ", mac_addr[ep_cnt]));
	}
	WBDEBUG(("\n"));
	WBDEBUG(("[w35und] Wb35_open<-\n"));
        #endif

	//TODO : put here temporarily
	hal_set_accept_broadcast( pHwData, 1); // open accept broadcast

	return 0;
}

int wb35_close( struct net_device *netdev )
{
	netif_stop_queue( netdev );

	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
	MOD_DEC_USE_COUNT;
	#endif

    #ifdef _PE_USB_INI_DUMP_
	WBDEBUG(("[w35und] Wb35_close\n"));
    #endif

	return 0;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
void wb35_disconnect( struct usb_device *udev, void *ptr )
#else
void wb35_disconnect( struct usb_interface *intf )
#endif
{
    PWBLINUX pWbLinux;
	#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
	PADAPTER Adapter = (PADAPTER)ptr;
	#else
	PADAPTER Adapter = usb_get_intfdata( intf );
	usb_set_intfdata( intf, NULL );
	#endif

        pWbLinux = &Adapter->WbLinux;

    #ifdef _PE_USB_INI_DUMP_
	WBDEBUG(("[w35und] wb35_disconnect -->\n"));
    #endif

	// Card remove
	WbWlanHalt( Adapter );

	#if LINUX_VERSION_CODE <KERNEL_VERSION(2,5,0)
	if( pWbLinux->netdev )
		kfree( pWbLinux->netdev );
	if( Adapter )
		kfree( Adapter );
	#else
	if( pWbLinux->netdev )
		free_netdev( pWbLinux->netdev );
	#endif

	#ifdef _PE_USB_INI_DUMP_
	WBDEBUG(("[w35und] wb35_disconnect <---\n"));
    #endif
}



